home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / timer.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  7KB  |  276 lines

  1. /* General purpose software timer facilities
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    $Id: timer.c 1.4 93/07/16 11:51:33 ROOT_DOS Exp $
  7. *    04 Jul 93    1.4        GT    Fix warnings.                                    *
  8. *
  9. *  ATARI Version by David Nash - dnash@chaos.demon.co.uk
  10. *
  11. *  redefine pause as Pause to prevent clash with definition in <unistd.h>
  12. ****************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include "global.h"
  16. #include "timer.h"
  17. #include "proc.h"
  18. #include "mbuf.h"
  19. #include "commands.h"
  20. #include "daemon.h"
  21. #include "hardware.h"
  22. #include "socket.h"
  23.  
  24. /* Head of running timer chain.
  25.  * The list of running timers is sorted in increasing order of expiration;
  26.  * i.e., the first timer to expire is always at the head of the list.
  27.  */
  28. struct timer *Timers;
  29.  
  30. static void t_alarm __ARGS((void *x));
  31.  
  32. /* Process that handles clock ticks */
  33. void
  34. timerproc(i,v1,v2)
  35. int i;
  36. void *v1,*v2;
  37. {
  38.     register struct timer *t;
  39.     register struct timer *expired;
  40.     char i_state;
  41.     void (**vf) __ARGS((void));
  42.  
  43.     for(;;){
  44.         i_state = dirps();    /* Tick is modified by an interrupt */
  45.         while(Tick == 0)
  46. #ifdef ATARI
  47.             pwait(NULL);        /* release the CPU - experimental    */
  48. #else            
  49.             pwait(&Tick);
  50. #endif            
  51.         Tick = 0;
  52.         restore(i_state);
  53.  
  54.         if(!istate()){
  55.             restore(1);
  56.             printf("timer: ints were off!\n");
  57.         }
  58.  
  59. #ifndef atari
  60.         /* Call the functions listed in config.c */
  61.         for(vf = Cfunc;*vf != NULL;vf++)
  62.             (*vf)();
  63. #endif
  64.  
  65.         tflush();    /* Flush current session output */
  66.         pwait(NULL);    /* Let them all do their writes */
  67.         rflush();    /* Flush out buffered console stuff */
  68.         fflush(stdout);    /* And flush out stdout too */
  69.  
  70.         if(Timers == NULLTIMER)
  71.             continue;    /* No active timers, all done */
  72.  
  73.         /* Initialize null expired timer list */
  74.         expired = NULLTIMER;
  75.  
  76.         /* Move expired timers to expired list. Note use of
  77.          * subtraction and comparison to zero rather than the
  78.          * more obvious simple comparison; this avoids
  79.          * problems when the clock count wraps around.
  80.          */
  81.         while(Timers != NULLTIMER && (Clock - Timers->expiration) >= 0){
  82.             if(Timers->next == Timers){
  83.                 printf("PANIC: Timer loop at %lx\n",
  84.                  (long)Timers);
  85.                 iostop();
  86.                 exit(1);
  87.             }
  88.             /* Save Timers since stop_timer will change it */
  89.             t = Timers;
  90.             stop_timer(t);
  91.             t->state = TIMER_EXPIRE;
  92.             /* Add to expired timer list */
  93.             t->next = expired;
  94.             expired = t;
  95.         }
  96.         /* Now go through the list of expired timers, removing each
  97.          * one and kicking the notify function, if there is one
  98.          */
  99.         while((t = expired) != NULLTIMER){
  100.             expired = t->next;
  101.             if(t->func){
  102.                 (*t->func)(t->arg);
  103.             }
  104.         }
  105.         pwait(NULL);    /* Let them run before handling more ticks */
  106.     }
  107. }
  108. /* Start a timer */
  109. void
  110. start_timer(t)
  111. struct timer *t;
  112. {
  113.     register struct timer *tnext;
  114.     struct timer *tprev = NULLTIMER;
  115.  
  116.     if(t == NULLTIMER)
  117.         return;
  118.     if(t->state == TIMER_RUN)
  119.         stop_timer(t);
  120.     if(t->duration == 0)
  121.         return;        /* A duration value of 0 disables the timer */
  122.  
  123.     t->expiration = Clock + t->duration;
  124.     t->state = TIMER_RUN;
  125.  
  126.     /* Find right place on list for this guy. Once again, note use
  127.      * of subtraction and comparison with zero rather than direct
  128.      * comparison of expiration times.
  129.      */
  130.     for(tnext = Timers;tnext != NULLTIMER;tprev=tnext,tnext = tnext->next){
  131.         if((tnext->expiration - t->expiration) >= 0)
  132.             break;
  133.     }
  134.     /* At this point, tprev points to the entry that should go right
  135.      * before us, and tnext points to the entry just after us. Either or
  136.      * both may be null.
  137.      */
  138.     if(tprev == NULLTIMER)
  139.         Timers = t;        /* Put at beginning */
  140.     else
  141.         tprev->next = t;
  142.  
  143.     t->next = tnext;
  144. }
  145. /* Stop a timer */
  146. void
  147. stop_timer(timer)
  148. struct timer *timer;
  149. {
  150.     register struct timer *t;
  151.     struct timer *tlast = NULLTIMER;
  152.  
  153.     if(timer == NULLTIMER || timer->state != TIMER_RUN)
  154.         return;
  155.  
  156.     /* Verify that timer is really on list */
  157.     for(t = Timers;t != NULLTIMER;tlast = t,t = t->next)
  158.         if(t == timer)
  159.             break;
  160.  
  161.     if(t == NULLTIMER)
  162.         return;        /* Should probably panic here */
  163.  
  164.     /* Delete from active timer list */
  165.     if(tlast != NULLTIMER)
  166.         tlast->next = t->next;
  167.     else
  168.         Timers = t->next;    /* Was first on list */
  169.  
  170.     t->state = TIMER_STOP;
  171. }
  172. /* Return milliseconds remaining on this timer */
  173. int32
  174. read_timer(t)
  175. struct timer *t;
  176. {
  177.     int32 remaining;
  178.  
  179.     if(t == NULLTIMER || t->state != TIMER_RUN)
  180.         return 0;
  181.     remaining = t->expiration - Clock;
  182.     if(remaining <= 0)
  183.         return 0;    /* Already expired */
  184.     else
  185.         return remaining * MSPTICK;
  186. }
  187. void
  188. set_timer(t,interval)
  189. struct timer *t;
  190. int32 interval;
  191. {
  192.     if(t == NULLTIMER)
  193.         return;
  194.     /* Round the interval up to the next full tick, and then
  195.      * add another tick to guarantee that the timeout will not
  196.      * occur before the interval is up. This is necessary because
  197.      * we're asynchronous with the system clock.
  198.      */    
  199.     if(interval != 0)
  200.         t->duration = 1 + (interval + MSPTICK - 1)/MSPTICK;
  201.     else
  202.         t->duration = 0;
  203. }
  204. /* Delay process for specified number of milliseconds.
  205.  * Normally returns 0; returns -1 if aborted by alarm.
  206.  *
  207.  * ATARI - renamed Pause (from pause) to prevent clash with <unistd.h>
  208.  */
  209.  
  210. int Pause(ms)
  211. int32 ms;
  212. {
  213.     int val;
  214.  
  215.     if(Curproc == NULLPROC || ms == 0)
  216.         return 0;
  217.     alarm(ms);
  218.     /* The actual event doesn't matter, since we'll be alerted */
  219.     while(Curproc->alarm.state == TIMER_RUN){
  220.         if((val = pwait(Curproc)) != 0)
  221.             break;
  222.     }
  223.     alarm(0L); /* Make sure it's stopped, in case we were killed */    
  224.     return (val == EALARM) ? 0 : -1;
  225. }
  226. static void
  227. t_alarm(x)
  228. void *x;
  229. {
  230.     alert((struct proc *)x,EALARM);
  231. }
  232. /* Send signal to current process after specified number of milliseconds */
  233. void
  234. alarm(ms)
  235. int32 ms;
  236. {
  237.     if(Curproc != NULLPROC){
  238.         set_timer(&Curproc->alarm,ms);
  239.         Curproc->alarm.func = t_alarm;
  240.         Curproc->alarm.arg = (char *)Curproc;
  241.         start_timer(&Curproc->alarm);
  242.     }
  243. }
  244. /* Convert time count in seconds to printable days:hr:min:sec format */
  245. char *
  246. tformat(t)
  247. int32 t;
  248. {
  249.     static char buf[17],*cp;
  250.     unsigned int days,hrs,mins,secs;
  251.     int minus;
  252.  
  253.     if(t < 0){
  254.         t = -t;
  255.         minus = 1;
  256.     } else
  257.         minus = 0;
  258.  
  259.     secs = (unsigned int) (t % 60);
  260.     t /= 60;
  261.     mins = (unsigned int) (t % 60);
  262.     t /= 60;
  263.     hrs = (unsigned int) (t % 24);
  264.     t /= 24;
  265.     days = (unsigned int) t;
  266.     if(minus){
  267.         cp = buf+1;
  268.         buf[0] = '-';
  269.     } else
  270.         cp = buf;
  271.     sprintf(cp,"%u:%02u:%02u:%02u",days,hrs,mins,secs);
  272.     
  273.     return buf;
  274. }
  275.     
  276.